package lct.fontcompiler;

import java.awt.Font;
import java.util.Vector;

import lct.font.*;
import lct.imag.*;
import lct.util.FileUtility;
import lct.util.PathUtility;

public class Program {
	private static XMLConverter s_xmlConverter;
	private static lct.font.XMLConverter s_fontXMLConverter;
	private static lct.font.BinaryConverter s_fontBinaryConverter;
	private static lct.imag.ImageConverter s_textImageConverter;
	private static lct.imag.BinaryConverter s_textBinaryConverter;
	
	private static final String TASK_OPTION = "-task=";
	private static final String TASK_EXAMPLE = "example";
	private static final String TASK_PACKAGE = "package";
	private static final String MANIFEST_FILE_PATH_OPTION = "-manifestFilePath=";
	private static final String TEMP_DIRECTORY_PATH_OPTION = "-tempDirectoryPath=";
	private static final String PACKAGE_FILE_PATH_OPTION = "-packageFilePath=";
	
	private static String s_task;
	private static String s_manifestFilePath;
	private static String s_tempDirectoryPath;
	private static String s_packageFilePath;
	private static boolean s_bigEndian = false;
	
	private static Manifest s_manifest;
	
	private static void processArguments(String[] args) {
		for (int index = 0; index < args.length; ++index) {
			String arg = args[index];
			if (arg.startsWith(TASK_OPTION)) {
				s_task = arg.substring(TASK_OPTION.length());
			}
			else if (arg.startsWith(MANIFEST_FILE_PATH_OPTION)) {
				s_manifestFilePath = arg.substring(MANIFEST_FILE_PATH_OPTION.length());
			}
			else if (arg.startsWith(TEMP_DIRECTORY_PATH_OPTION)) {
				s_tempDirectoryPath = arg.substring(TEMP_DIRECTORY_PATH_OPTION.length());
			}
			else if (arg.startsWith(PACKAGE_FILE_PATH_OPTION)) {
				s_packageFilePath = arg.substring(PACKAGE_FILE_PATH_OPTION.length());
			}
		}
	}
	
	private static void generateExamples() {
		Font font = new Font("Arial", Font.BOLD, 16);
		final int CELL_WIDTH = 32;
		final int CELL_HEIGHT = 32;
		
		Sheet sheet = Examples.createSheet(CELL_WIDTH, CELL_HEIGHT, font);
		s_fontXMLConverter.storeSheet(sheet, "./example_sheet.xml");
		
		Texture sheetTexture = Examples.createSheetTexture(CELL_WIDTH, CELL_HEIGHT, font);
		s_textImageConverter.storeTextureTGA(sheetTexture, "./example_texture.tga");
		
		Texture gridTexture = Examples.createGridTexture(CELL_WIDTH, CELL_HEIGHT);
		s_textImageConverter.storeTextureTGA(gridTexture, "./example_grid_texture.tga");
		
		Manifest manifest = Examples.createManifest("./");
		s_xmlConverter.storeManifest(manifest, "./example_manifest.xml");
	}
	
	private static void processPackage() {
		if ((s_manifestFilePath == null) || (s_tempDirectoryPath == null) || (s_packageFilePath == null)) {
			System.err.println("Invalid arguments for package task.");
			System.exit(-1);
		}
		
		s_manifest = s_xmlConverter.loadManifest(s_manifestFilePath);
		if (s_manifest == null) {
			System.err.println("Error loading manifest.");
			System.exit(-1);
		}
		
		boolean anyEntryProcessed = false;
		Vector<String> binaryFilePathVector = new Vector<String>();
		
		String sheetTempDirectoryPath = PathUtility.combineFull(s_tempDirectoryPath, "sheet");
		FileUtility.createDirectory(sheetTempDirectoryPath);
		
		for (Manifest.SheetEntry sheetEntry: s_manifest.sheetEntryVector) {
			String binaryFileName = PathUtility.getFileNameNoExtension(sheetEntry.filePath) + ".bin";
			String binaryFilePath = PathUtility.combineFull(sheetTempDirectoryPath, binaryFileName);
			binaryFilePathVector.add(binaryFilePath);
			
			anyEntryProcessed |= processSheet(sheetEntry.filePath, binaryFilePath);
		}
		
		String textureTempDirectoryPath = PathUtility.combineFull(s_tempDirectoryPath, "texture");
		FileUtility.createDirectory(textureTempDirectoryPath);
		
		for (Manifest.TextureEntry textureEntry: s_manifest.textureEntryVector) {
			String binaryFileName = PathUtility.getFileNameNoExtension(textureEntry.filePath) + ".bin";
			String binaryFilePath = PathUtility.combineFull(textureTempDirectoryPath, binaryFileName);
			binaryFilePathVector.add(binaryFilePath);
			
			anyEntryProcessed |= processTexture(textureEntry.filePath, binaryFilePath);
		}
		
		if (anyEntryProcessed || !FileUtility.exists(s_packageFilePath)) {
			FileUtility.consolidateFiles(binaryFilePathVector, s_packageFilePath);
		}
	}
	
	private static boolean processSheet(String xmlFilePath, String binaryFilePath) {
		if (!FileUtility.exists(xmlFilePath)) {
			System.err.println("Referenced sheet file does not exist: " + xmlFilePath);
			System.exit(-1);
		}
		
		if (FileUtility.isOutdated(binaryFilePath, xmlFilePath)) {
			Sheet sheet = s_fontXMLConverter.loadSheet(xmlFilePath);
			s_fontBinaryConverter.storeSheet(sheet, binaryFilePath, s_bigEndian);
			return true;
		}
		else {
			return false;
		}
	}
	
	private static boolean processTexture(String imageFilePath, String binaryFilePath) {
		if (!FileUtility.exists(imageFilePath)) {
			System.err.println("Referenced texture file does not exist: " + imageFilePath);
			System.exit(-1);
		}
		
		if (FileUtility.isOutdated(binaryFilePath, imageFilePath)) {
			Texture texture = s_textImageConverter.loadTextureTGA(imageFilePath);
			s_textBinaryConverter.storeTexture(texture, binaryFilePath, s_bigEndian);
			return true;
		}
		else {
			return false;
		}
	}
	
	public static void main(String[] args) {
		s_xmlConverter = new XMLConverter();
		s_fontXMLConverter = new lct.font.XMLConverter();		
		s_fontBinaryConverter = new lct.font.BinaryConverter();
		s_textImageConverter = new lct.imag.ImageConverter();
		s_textBinaryConverter = new lct.imag.BinaryConverter();
		
		processArguments(args);
		
		switch (s_task) {
		case TASK_EXAMPLE:
			generateExamples();
			break;
		case TASK_PACKAGE:
			generateExamples(); // TEMP!!!
			processPackage();
			break;
		default:
			System.err.println("Invalid task specified");
			System.exit(-1);
		}
	}
}
